//#![deny(warnings)]

extern crate base64;
extern crate crypto;
extern crate futures;
extern crate hyper;
extern crate rand;
extern crate tokio_core;
#[macro_use]
extern crate mysql;
extern crate chrono;

pub mod crypt;
pub mod datacheck;
pub mod httpcon;
pub mod mybase64;

use tokio_core::reactor::Core;

use std::cell::RefCell;
use std::rc::Rc;

use rand::{OsRng, Rng};

use mysql as my;

use std::sync::mpsc;
use std::thread;
use std::time::Duration;
//use std::sync::Mutex;
use std::sync::{Arc, Mutex};

use chrono::format::ParseResult;
use chrono::prelude::*;
use std::fmt::Display;
use std::time::SystemTime;

// use httpcon as hc;
use crypt as cy;
use datacheck as dc;

use mybase64 as myb64;

// use gui::Draw;

// #[no_mangle]
// pub extern fn add_numbers(number1: i32, number2: i32) -> i32 {
//     println!("Hello from rust!");
//     number1 + number2
// }

// =============================================================================闭包/委托/函数指针

// 这个泛型 是个 闭包 函数指针， 委托  u32参数 返回 u32的 闭包/委托/函数指针
struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    calculation: T,
    value: Option<u32>,
}

impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            value: None,
        }
    }

    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            }
        }
    }
}

fn generate_workout(intensity: u32, random_number: u32) {
    let mut expensive_result = Cacher::new(|num| {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num
    });

    if intensity < 25 {
        println!("Today, do {} pushups!", expensive_result.value(intensity));
        println!("Next, do {} situps!", expensive_result.value(intensity));
    } else {
        if random_number == 3 {
            println!("Take a break today! Remember to stay hydrated!");
        } else {
            println!(
                "Today, run for {} minutes!",
                expensive_result.value(intensity)
            );
        }
    }
}

// ===================================================================================生命周期标注

/// 通过标记 `a 表示两个值生命周期一样，且已最小最短那个为准，
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn longest1<'a>(x: &'a str, y: &str) -> &'a str {
    x
}

fn live_test() {
    let string1 = String::from("long string is long");

    {
        let string2 = String::from("xyz");
        let result = longest(string1.as_str(), string2.as_str());
        println!("The longest string is {}", result);
    }
    // 这里生命周期注解（longest<'a>函数）表示 以（string1， string2）最小生命周期为准。
    // 但是string2生命周期在上面大括号后已经结束，所以下面这个语句无法编译。
    // println!("The longest string is {}", result);
}

fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str
where
    T: Display,
{
    println!("Announcement! {}", ann);
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

// ================================================================================mysql数据库操作

#[derive(Debug, PartialEq, Eq)]
struct Payment {
    customer_id: i32,
    amount: i32,
    account_name: Option<String>,
}

#[derive(Debug, PartialEq, Eq)]
struct Area {
    sysno: i32,
    areacode: Option<String>,
    areaname: Option<String>,
}

fn mysql_call() {
    // See docs on the `OptsBuilder`'s methods for the list of options available via URL.
    // let pool = my::Pool::new("mysql://wlaccountuser:wl258@localhost:3306/wl_account_db").unwrap();

    let pool = my::Pool::new("mysql://huawei:PyzMeJjq3J6CFPQx@192.168.31.58:3307/hw_ocss").unwrap();

    // Let's create payment table.
    // Unwrap just to make sure no error happened.
    // pool.prep_exec(r"CREATE TABLE payment (
    //                      customer_id int not null,
    //                      amount int not null,
    //                      account_name text
    //                  )", ()).unwrap();

    println!("好像 创建表 执行成功了？ {:?}", 888i32);
    // let payments = vec![
    //     Payment { customer_id: 1, amount: 2, account_name: None },
    //     Payment { customer_id: 3, amount: 4, account_name: Some("foo".into()) },
    //     Payment { customer_id: 5, amount: 6, account_name: None },
    //     Payment { customer_id: 7, amount: 8, account_name: None },
    //     Payment { customer_id: 9, amount: 10, account_name: Some("bar".into()) },
    // ];

    // Let's insert payments to the database
    // We will use into_iter() because we do not need to map Stmt to anything else.
    // Also we assume that no error happened in `prepare`.
    // for mut stmt in pool.prepare(r"INSERT INTO payment
    //                                    (customer_id, amount, account_name)
    //                                VALUES
    //                                    (:customer_id, :amount, :account_name)").into_iter() {
    //     for p in payments.iter() {
    //         // `execute` takes ownership of `params` so we pass account name by reference.
    //         // Unwrap each result just to make sure no errors happened.
    //         stmt.execute(params!{
    //             "customer_id" => p.customer_id,
    //             "amount" => p.amount,
    //             "account_name" => &p.account_name,
    //         }).unwrap();
    //     }
    // }
    println!("好像 插入数据 表 执行成功了？ {:?}", 999i32);

    // Let's select payments from database
    let selected_payments: Vec<Area> = pool
        .prep_exec("select sysno, areacode, areaname from bsarea", ())
        .map(|result| {
            // In this closure we will map `QueryResult` to `Vec<Payment>`
            // `QueryResult` is iterator over `MyResult<row, err>` so first call to `map`
            // will map each `MyResult` to contained `row` (no proper error handling)
            // and second call to `map` will map each `row` to `Payment`
            result
                .map(|x| x.unwrap())
                .map(|row| {
                    // ⚠️ Note that from_row will panic if you don't follow your schema
                    let (sysno, areacode, areaname) = my::from_row(row);
                    Area {
                        sysno: sysno,
                        areacode: areacode,
                        areaname: areaname,
                    }
                })
                .collect() // Collect payments so now `QueryResult` is mapped to `Vec<Payment>`
        })
        .unwrap(); // Unwrap `Vec<Payment>`

    // Now make sure that `payments` equals to `selected_payments`.
    // Mysql gives no guaranties on order of returned rows without `ORDER BY`
    // so assume we are lukky.
    // assert_eq!(payments, selected_payments);

    for item in &selected_payments {
        println!(" Object = {:?} ", &item);
    }
    println!("Yay! wao 全成功了？  {:?}  ", 999i32);
}

// ================================================================ trait 泛型 / 接口 / 行为协议

pub trait Shit {
    fn ShitInAss(&self) -> String;
    fn FuckAss(&self) -> String {
        String::from("(Fuck you...)")
    }
}

pub struct NewsAss {
    pub shit: String,
}

impl Shit for NewsAss {
    fn ShitInAss(&self) -> String {
        format!("{} In The Ass !!", self.shit)
    }
}

pub fn notify(item: impl Shit) -> impl Shit {
    println!("Breaking news! {}", item.FuckAss());
    item
}

pub fn notify2<T: Shit>(item: &T) {
    println!("Breaking news! 222 {}", item.ShitInAss());
}

pub fn notify3<T: Shit>(item: &T) {
    println!("Breaking news! 222 {}", item.FuckAss());
}

// =================================================闭包/委托/函数指针
struct XXX<T>
where
    T: Fn(i32) -> i32,
{
    pub xxx: T,
}

impl<T> XXX<T>
where
    T: Fn(i32) -> i32,
{
    fn new(x: T) -> XXX<T> {
        XXX { xxx: x }
    }
}
// Closures
fn closures(i: i32) -> i32 {
    let res = XXX::new(|n: i32| n + 10);
    println!(" 自己创建的闭包 closures 执行 : {:?}", (res.xxx)(i));
    return 21i32;
}

// ===========================================

fn thread_run_1() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

fn thread_run_2() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    handle.join().unwrap();

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}

fn closure001() {
    let v = vec![1, 2, 3];

    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });

    handle.join().unwrap();
}

fn channel001() {
    println!(
        "channel001 线程里面 向通道发送消息，主线程 没有接收消息 {:?}",
        300
    );
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi001");
        tx.send(val).unwrap();
    });
    let received = rx.recv().unwrap();
    println!("channel001 Got: {}", received);
}

fn channel002() {
    println!(
        "channel002 线程里面 向通道发送消息，主线程接收 发送消息 {:?}",
        300
    );
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi you");
        tx.send(val).unwrap();
    });

    let received = rx.recv().unwrap();
    println!("channel002 Got: {}", received);
}

fn channel003() {
    println!(
        "channel003 线程里面循环 向通道发送消息，主线程接收 发送消息 {:?}",
        300
    );
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("channel003 Got: {}", received);
    }
}

fn channel004() {
    println!(
        "channel004 两个线程里面循环 向一个通道发送消息，主线程接收 发送消息 {:?}",
        300
    );
    let (tx, rx) = mpsc::channel();

    let tx1 = mpsc::Sender::clone(&tx);
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];

        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    thread::spawn(move || {
        let vals = vec![
            String::from("more"),
            String::from("messages"),
            String::from("for"),
            String::from("you"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("channel004 Got: {}", received);
    }
}

// --------------------------------- 线程借用 变量
pub fn thread_borrow1(soustr: Arc<Mutex<String>>) {
    let (tx, rx) = mpsc::channel();
    let sc = soustr.clone();
    thread::spawn(move || {
        for val in sc.lock().unwrap().chars() {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("thread_borrow Got: {}", received);
    }
}

pub fn thread_borrow2(soustr: Arc<Mutex<String>>) {
    let (tx, rx) = mpsc::channel();
    let sc = soustr.clone();
    thread::spawn(move || {
        for val in sc.lock().unwrap().bytes() {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("thread_borrow Got: {}", received);
    }
}

pub fn thread_borrow(soustr: &'static String) {
    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        for val in soustr.chars() {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("thread_borrow Got: {}", received);
    }
}

/// 单线程 互斥锁
fn mutex001() {
    println!(" 单线程 互斥锁 {:?}", 500);
    let m = Mutex::new(5); // 互斥锁5

    {
        let mut num = m.lock().unwrap(); //上锁
        *num = 6; //更新值
    } //解锁

    println!("m = {:?}", m); //打印
}

/// 多线程原子 互斥锁
/// Rc<T> 来允许多个线程拥有 Mutex<T> ，但是编译不过，因为所有权不能再线程间安全转移
/// Arc<T> 正是 这么一个类似 Rc<T> 并可以安全的用于并发环境的类型。
fn mutex_arc_001() {
    println!(" 多线程原子 互斥锁 {:?}", 500);
    println!(
        " Rc<T> 来允许多个线程拥有 Mutex<T> ，但是编译不过，因为所有权不能再线程间安全转移 {:?}",
        500
    );
    println!(
        " Arc<T> 正是 这么一个类似 Rc<T> 并可以安全的用于并发环境的类型。 {:?}",
        500
    );
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();

            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

// ======================
// 契约，特征，接口
pub trait Draw {
    fn draw(&self);
}
// // 结构
pub struct Screen {
    pub components: Vec<Box<dyn Draw>>,
}
// 结构方法组，行为，实现
impl Screen {
    pub fn run(&self) {
        for component in self.components.iter() {
            component.draw();
        }
    }
}

// 泛型结构，必须实现了 trait（特征锲约） Draw 的泛型
// pub struct Screen<T: Draw> {
//     pub components: Vec<T>,
// }

// impl<T> Screen<T>
//     where T: Draw {
//     pub fn run(&self) {
//         for component in self.components.iter() {
//             component.draw();
//         }
//     }
// }

pub struct Button {
    pub width: u32,
    pub height: u32,
    pub label: String,
}

// 为Button 实现 trait 特征/锲约
impl Draw for Button {
    fn draw(&self) {
        // 实际绘制按钮的代码
        println!("绘制 Button -- {:?}", 101);
        println!("绘制 Button label -- {:?}", self.label);
    }
}

pub struct SelectBox {
    width: u32,
    height: u32,
    options: Vec<String>,
}
// 为 SelectBox 实现 trait 特征 Draw
impl Draw for SelectBox {
    fn draw(&self) {
        // code to actually draw a select box
        println!("绘制 SelectBox -- {:?}", 100);
        for op in self.options.iter() {
            println!("绘制 SelectBox option -- {:?}", op);
        }
    }
}

fn trait_draw_test001() {
    let screen = Screen {
        components: vec![
            Box::new(SelectBox {
                width: 75,
                height: 10,
                options: vec![
                    String::from("Yes"),
                    String::from("Maybe"),
                    String::from("No"),
                ],
            }),
            Box::new(Button {
                width: 50,
                height: 10,
                label: String::from("OK"),
            }),
        ],
    };

    screen.run();
}

// ===========
fn time_x() {
    let sys_time = SystemTime::now();
    println!("now time {:?}", sys_time);
    let local: DateTime<Local> = Local::now();
    println!(
        " date ({:?})",
        local.format("%Y-%m-%d %H:%M:%S").to_string()
    );
    // 字符串转换时间类型
    let t1: ParseResult<DateTime<FixedOffset>> =
        DateTime::parse_from_str("2020-03-28 21:00:09 +09:00", "%Y-%m-%d %H:%M:%S %z");
    println!("t1: ParseResult<DateTime<FixedOffset>>({:?})", t1);
    // .ok().unwrap() 很重要
    let t2: ParseResult<DateTime<Utc>> =
        Utc.datetime_from_str("2020-03-06 12:00:09", "%Y-%m-%d %H:%M:%S");
    println!(
        "t2: ParseResult<DateTime<Utc>>({:?})",
        t2.ok().unwrap().format("%y-%m-%d %H:%M:%S").to_string()
    );
    //
    let t3: DateTime<Local> = Local
        .datetime_from_str("2020-03-28 12:00:09", "%Y-%m-%d %H:%M:%S")
        .ok()
        .unwrap();
    println!("t3: DateTime<Local>({:?})", t3);
}

fn pt(st: &str) {
    println!("fn 内部打印 借用 参数 {:?}", st);
}

// ============= 结构 全数字的所有权问题

#[derive(Debug)]
struct HasNumArray {
    id: i64,
    price: f64,
    status: u8,
    xr: [i32; 10],
}

#[derive(Debug)]
struct HasNumArray2 {
    id: i64,
    price: f64,
    status: u8,
    xr: Vec<i32>,
}

#[derive(Debug)]
struct HasString<'a> {
    id: i64,
    price: f64,
    status: u8,
    name: &'a str,
}

#[derive(Debug)]
struct HasString1 {
    id: i64,
    price: f64,
    status: u8,
    name: String,
}

#[derive(Debug)]
struct HasString2<'b> {
    id: i64,
    price: f64,
    status: u8,
    name: &'b String,
}

pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(Read more summarize...)")
    }
}

// trait Summary 要 impl 到 HasString1， 但是可以不写、不实现有默认实现的方法，然后就可以当作 trait Summary使用
impl Summary for HasString1 {
    // add code here
}

impl Summary for i64 {
    fn summarize(&self) -> String {
        format!("(Read more i64 summarize...{})", self)
    }
}

// ============================= 测试全数字结构能否拷贝，且不考虑所有权

#[derive(Debug)]
struct AllNum {
    id: i64,
    price: f64,
    status: u8,
}

fn print_num(val: i64) {
    println!("AllNum : id:{:?} ", val);
}

fn print_num_other(val: i64) {
    println!("AllNum Other : id:{:?} ", val);
}

fn print_all_num_struct(val: &AllNum) {
    println!(
        "AllNum : id:{:?} , price: {:?} , status: {:?}",
        val.id, val.price, val.status
    );
}

fn print_all_num_struct_other(val: AllNum) {
    println!(
        "AllNum Other : id:{:?} , price: {:?} , status: {:?}",
        val.id, val.price, val.status
    );
}

fn test_allnum_nopower() {
    let v: i64 = 3836527;
    print_num(v);
    print_num_other(v); // 单纯基础 数值 类型无需考虑所有权，都是拷贝的

    let vallnum = AllNum {
        id: 93838i64,
        price: 39374.34f64,
        status: 32u8,
    };
    print_all_num_struct(&vallnum); // 证实，结构 必须考虑所有权
    print_all_num_struct_other(vallnum); // 结构要考虑所有权问题，单纯基础数值类型无需考虑所有权
}

// ====================================== udp

use std::net::UdpSocket;

fn udp_server() -> std::io::Result<()> {
    {
        let mut socket = UdpSocket::bind("127.0.0.1:34254")?;

        // Receives a single datagram message on the socket. If `buf` is too small to hold
        // the message, it will be cut off.
        let mut buf = [0; 2048];
        let (amt, src) = socket.recv_from(&mut buf)?;

        // Redeclare `buf` as slice of the received data and send reverse data back to origin.
        let buf = &mut buf[..amt];
        buf.reverse();
        socket.send_to(buf, &src)?;
    } // the socket is closed here
    Ok(())
}

fn udp_send(msg: String) -> std::io::Result<()> {
    {
        let mut socket = UdpSocket::bind("127.0.0.1:34254")?;

        // Receives a single datagram message on the socket. If `buf` is too small to hold
        // the message, it will be cut off.
        let mut buf = [0; 10];
        let (amt, src) = socket.recv_from(&mut buf)?;

        // Redeclare `buf` as slice of the received data and send reverse data back to origin.
        let buf = &mut buf[..amt];
        buf.reverse();
        socket.send_to(buf, &src)?;
    } // the socket is closed here
    Ok(())
}

fn only_server(ip: &str, port: &str) -> std::io::Result<()> {
    let udp_addr = format!("{ip}:{port}", ip = ip, port = port);
    let mut socket = UdpSocket::bind(udp_addr)?;
    let mut buf = [0; 2048];
    let (amt, src) = socket.recv_from(&mut buf)?;
    let rcv_msg = std::str::from_utf8(&buf[..amt]).unwrap();
    println!(
        "Rust 接收到 UDP 客户端 [{:?}] 发来消息 ： 【{:?}】",
        src, rcv_msg
    );
    Ok(())
}

fn only_send(ip: &str, port: &str, msg: &String) -> std::io::Result<()> {
    let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address 链接失败 ");
    let msg_bytes = msg.as_bytes();
    let msg_count = msg_bytes.len();
    println!("udp send msg len : {:?}", msg_count);
    let udp_addr = format!("{ip}:{port}", ip = ip, port = port);
    socket
        .send_to(msg_bytes, udp_addr)
        .expect("couldn't send data 发送失败 ");
    Ok(())
}

fn test_udp() {
    let udp_msg = String::from(" 发送 含中文的 udp 信息 《--0--》 ...");
    only_send("127.0.0.1", "51425", &udp_msg);
    println!(" MSG : [{:?}] 发送完毕.", udp_msg);
    only_server("127.0.0.1", "34255");
}

// ----------

use std::io::prelude::*;
use std::net::{TcpListener, TcpStream};

fn handle_client(stream: &mut TcpStream) -> std::io::Result<()> {
    const buff_size: usize = 1024usize;
    // match stream {
    //     Ok(stream) => {
    //         // stream.read(&mut [0; buf_size])?;
    //         let mut buf = [0; buff_size];
    //         while true {
    //             let len = stream.peek(&mut buf).expect("peek failed");
    //             if len <= 0 {
    //                 return;
    //             }
    //             let rcv_msg = std::str::from_utf8(&buf[..amt]).unwrap();
    //             println!("Rust 接收到 TCP 客户端 发来消息 ： 【{:?}】", rcv_msg);
    //         }

    //     }
    //     Err(e) => { println!(" bad ass recv tcp msg ..."); }
    // }

    let mut buf = [0; buff_size];
    while true {
        // let len = stream.peek(&mut buf).expect("peek failed");
        let len = stream.read(&mut buf)?;
        let rcv_msg = std::str::from_utf8(&buf[..len]).unwrap();
        if rcv_msg == r#"bye"# {
            println!(" TCP Close  {:?}", 39849384);
            ()
        }
        println!("Rust 接收到 TCP 客户端 发来消息 ： 【{:?}】", rcv_msg);
        // stream.write(&[1])?;
        let send_msg: &[u8] = "bye".as_bytes();
        stream.write(&send_msg)?;
    }
    Ok(())
}

fn tcp_server(ip: &str, port: &str) -> std::io::Result<()> {
    let tcp_server_addr = format!("{ip}:{port}", ip = ip, port = port);
    let listener = TcpListener::bind(tcp_server_addr)?;
    const BUFF_SIZE: usize = 1024usize;
    // accept connections and process them serially
    for stream in listener.incoming() {
        //handle_client(&mut stream?);
        match stream {
            Ok(st) => {
                let mut s = &st;
                let mut buf = [0; BUFF_SIZE];
                let len = s.read(&mut buf)?;
                let rcv_msg = std::str::from_utf8(&buf[..len]).unwrap();
                if rcv_msg == r#"bye"# {
                    println!(" TCP Close  {:?}", 39849384);
                    ()
                }
                println!("Rust 接收到 TCP 客户端 发来消息 ： 【{:?}】", rcv_msg);
                // stream.write(&[1])?;
                let send_msg: &[u8] = "bye".as_bytes();
                s.write(&send_msg)?;
            }
            Err(s) => {
                println!("Rust incoming 流获取失败 {:?}", s);
            }
        }
    }
    Ok(())
}

fn test_tcp_server() {
    tcp_server("127.0.0.1", "34257");
}

/// ==========  main 程序方法入口
fn main() {
    let str2: &str = "程序已经开始运行...";
    println!("info {:?}", format!("format {x1}", x1 = &str2));
    println!("{number:>width$}", number = 1, width = 6); // 打印1,前面控制宽度6
    println!("{number:>0width$}", number = 1, width = 6); //打印1，前面用0填充宽度6
    pt(&str2);
    let v1 = HasString1 {
        id: 999800i64,
        price: 120.25f64,
        status: 12u8,
        name: String::from("big name "),
    };
    println!("trait Summary 要 impl 到 HasString1， 但是可以不写、不实现有默认实现的方法，然后就可以当作 trait Summary使用： new tweet: {}", v1.summarize());
    let v2_i64 = 9987373;
    println!(
        "为 i64 类型实现 trait Summary 而且不是 默认实现： new tweet: {}",
        v2_i64.summarize()
    );

    test_allnum_nopower();
    //
    myb64::base64_thread_test();
    //
    // test_udp();
    // test_tcp_server();
    // // let mut r = httpclient(1);
    // //httpclient_get();
    // //httpclient_get2();
    // //httpClient_post1();
    // //httpClient_newuser();
    // //let url:String = String::from("http://localhost:9011/api/UserAccount/Insert");
    // //let jsonStr:String = String::from(r#"{"Account":"admin1", "Password": "112233", "AccountID": "1"}"#);

    // let url:String = String::from("http://localhost:57788/Report/QueryPageRebateOrderReport");
    // let jsonStr:String = String::from(r#"{"PageNo":1, "PageSize": 20, "BusinessDateBegin": "2019-01-01", "BusinessDateEnd": "2019-10-21"}"#);
    // //httpClient_post(url, jsonStr);

    // let url:String = String::from("http://localhost:50161/RebateOrderReport/InQueryPageRebateOrderReport");
    // let jsonStr:String = String::from(r#"{"PageNo":1, "PageSize": 20, "BusinessDateBegin": "2019-01-01", "BusinessDateEnd": "2019-10-28", "MerchantIds": [28, 29, 30, 31, 32]}"#);

    // let url:String = String::from("http://localhost:50161/Inventory/VendibleDSOReport");
    // let jsonStr:String = String::from(r#"{"PageNo":1, "PageSize": 100}"#);

    // let url:String = String::from("http://localhost:50161/Sale/ProductSalesPolicyReport");
    // let jsonStr:String = String::from(r#"{"PageNo":1, "PageSize": 100}"#);

    // let url:String = String::from("http://localhost:50161/Sale/ClerksCommissionDetailsReport");
    // let jsonStr:String = String::from(r#"{"PageNo":1, "PageSize": 100}"#);

    let url: String =
        String::from("http://report.trade.hw.pisendev.com/Sale/ClerksCommissionDetailsReport");
    let jsonStr: String = String::from(r#"{"PageNo":1, "PageSize": 100}"#);
    // hc::httpClient_post(url, jsonStr);

    // println!("\r\n");
    // let ass = NewsAss{ shit: String::from("BIG ASS"), };
    // println!(" trait test : {}", ass.ShitInAss());
    // println!(" trait test : {}", ass.FuckAss());

    // //ass = notify(ass);
    // notify2(&ass); // 先 借用 才行，后借用就会报错 所有权 被移走了
    // // notify2(&ass); // 放在 notify(ass); 后， 后借用就会报错 所有权 被移走了
    // notify3(&ass);

    // notify(ass);
    // /////////////////////////////////
    // let mut s1 = String::from("foo"); // 定义可变
    // let s2 = "bar"; // 定义另一个
    // s1.push_str(s2); // push到 s1中，
    // println!("s2 is {}", s2); //打印s2，s2这里是切片，所以可以运行
    // println!("s1 is {}", s1); //打印s2，s2这里是切片，所以可以运行

    let msg = String::from("愤怒是魔鬼！");
    cy::test_crypto(&msg);

    // mysql_call();

    // let res1 = generate_workout(100u32, 20u32);
    // println!("闭包测试 ： generate_workout(100u32, 20u32) 结果 ： {:?}", res1);
    // let res1 = generate_workout(100u32, 3u32);
    // println!("闭包测试 ： generate_workout(100u32, 3u32) 结果 ： {:?}", res1);
    // let res1 = generate_workout(20u32, 3u32);
    // println!("闭包测试 ： generate_workout(20u32, 3u32) 结果 ： {:?}", res1);

    // //let ffn = XXX::new(move |x: i32| x+10 );
    // closures(34i32);

    // let c1 = |n: i32| -> i32 {
    //     let m = n + 100;
    //     println!("let 直接 闭包 执行 : {:?}", m);
    //     m
    // };

    // c1(99);

    // ====
    // thread_run_1();

    // thread_run_2();
    // //
    // closure001();
    // //
    // channel001();
    // channel002();
    // channel003();
    // channel004();
    //
    let big_str: String = String::from(
        r#"编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs编译器甚至会提示我们这只能用于闭包！ 当闭包从环境中捕获一个值，闭包会在闭包体中储存这个值以供使用。这会使用内存并产生额外的开销，在更一般的场景中，当我们不需要闭包来捕获环境时，我们不希望产生这些开销。因为函数从未允许捕获环境，定义和使用函数也就从不会有这些额外开销。 闭包可以通过三种方式捕获其环境，他们直接对应函数的三种获取参数的方式：获取所有权，可变借用和不可变借用。这三种捕获值的方式被编码为如下三个 Fn trait： FnOnce 消费从周围作用域捕获的变量，闭包周围的作用域被称为其 环境，environment。为了消费捕获到的变量，闭包必须获取其所有权并在定义闭包时将其移动进闭包。其名称的 Once 部分代表了闭包不能多次获取相同变量的所有权的事实，所以它只能被调用一次。 FnMut 获取可变的借用值所以可以改变其环境 Fn 从其环境获取不可变的借用值 当创建一个闭包时，Rust 根据其如何使用环境中变量来推断我们希望如何引用环境。由于所有闭包都可以被调用至少一次，所以所有闭包都实现了 FnOnce 。那些并没有移动被捕获变量的所有权到闭包内的闭包也实现了 FnMut ，而不需要对被捕获的变量进行可变访问的闭包则也实现了 Fn 。 在示例 13-12 中，equal_to_x 闭包不可变的借用了 x（所以 equal_to_x 具有 Fn trait），因为闭包体只需要读取 x 的值。 如果你希望强制闭包获取其使用的环境值的所有权，可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。 第十六章讨论并发时会展示更多 move 闭包的例子，不过现在这里修改了示例 13-12 中的代码（作为演示），在闭包定义中增加 move 关键字并使用 vector 代替整型，因为整型可以被拷贝而不是移动；注意这些代码还不能编译： 文件名: src/main.rs"#,
    );

    let amt_str = Arc::new(Mutex::new(String::from(big_str.clone())));
    let enbase64_res = myb64::base64encode_thread(amt_str);
    println!(" EN BASE64 RESULT : {:?}", enbase64_res);
    //let str2: String = String::from(big_str.clone());
    //let b64_res = myb64::base64encode(&str2);
    //println!(" base64 result: {:?}", b64_res);
    let code_str = Arc::new(Mutex::new(String::from(enbase64_res)));
    let debase64_res = myb64::base64decode_thread(code_str);
    println!(" DE BASE64 RESULT : {:?}", debase64_res);

    myb64::base64_test();
    myb64::base64_thread_test();
    //thread_borrow2(amt_str);
    // 静态生命周期 String 暂时失败
    // let st_str: String = String::from("9876543210");
    // let st_str1: &'static String = &st_str[..];
    // thread_borrow(st_str1);
    // //
    // mutex001();
    // //
    // mutex_arc_001();
    // //
    // trait_draw_test001();

    // dc::check();
    // dc::exec_sql();

    // dc::query_tc();
    time_x();
}
